#ifndef FACTORY_H
#define FACTORY_H

#include <iostream>

enum class ProductId {
  kMyProduct = 0,
  kYourProduct,
  kTheirProduct
};

class Product {};

class Factory {
public:
  virtual Product* CreateProduct() {}
  virtual Product* CreateProduct(ProductId id) {}
};

class MyProduct : public Product {
public:
  MyProduct() {
    std::cout << "MyProduct" << std::endl;
  }
};

class YourProduct : public Product {
public:
  YourProduct() {
    std::cout << "YourProduct" << std::endl;
  }
};

class TheirProduct : public Product {
public:
  TheirProduct() {
    std::cout << "TheirProduct" << std::endl;
  }
};

// form 1:
template<class TheProduct>
class StandardFactory : public Factory {
public:
  virtual Product* CreateProduct() {
    return new TheProduct();
  }
};

// form 2:
class NormalFactory : public Factory {
public:
  virtual Product* CreateProduct(ProductId id) {
    switch(id) {
      case ProductId::kMyProduct :
        return new MyProduct();
      case ProductId::kYourProduct :
        return new YourProduct();
      case ProductId::kTheirProduct :
        return new TheirProduct();
      default : 
        return new MyProduct();
    }
  }
};

#endif // FACTORY_H
